import { useCallback, useEffect, useRef, useState } from 'react';
import { flushSync } from 'react-dom';
import type { SnapPoint } from '../types';
import { useGestureRecognition } from './useGestureRecognition';

interface UseSnapPointsProps {
  snapPoints?: SnapPoint[];
  initialSnap?: number;
  onSnap?: (snapIndex: number, snapValue: SnapPoint) => void;
  onClose?: () => void; // 添加关闭回调
  position?: 'bottom' | 'top' | 'left' | 'right';
  open: boolean;
  /** 启用手势识别增强 */
  enableGestureRecognition?: boolean;
  /** 快速滑动速度阈值 (px/ms) */
  fastSwipeThreshold?: number;
}

/**
 * Snap Points 吸附系统 Hook
 *
 * 🎯 核心思路：
 * 1. 抽象化吸附点定义：支持多种格式 (像素、百分比、距离顶部等)
 * 2. 智能吸附算法：根据当前位置和拖拽距离选择最合适的吸附点
 * 3. 实时响应：拖拽过程中实时计算位置，释放时平滑吸附
 * 4. 状态同步：使用 flushSync 确保拖拽时的即时响应
 *
 * 🔢 吸附点格式支持：
 * - 0: 关闭状态
 * - 1: 全屏状态
 * - 0.5: 50% 窗口高度
 * - -100: 距离顶部 100px
 * - 300: 固定 300px 高度
 *
 * 🎮 交互设计：
 * - 拖拽开始：立即响应，无延迟
 * - 拖拽中：实时跟随手指/鼠标
 * - 拖拽结束：智能选择最近吸附点
 * - 按钮控制：平滑动画到指定位置
 *
 * ⚡ 性能优化：
 * - flushSync 用于用户交互，确保同步更新
 * - 避免在 useEffect 中使用 flushSync
 * - 合理的依赖数组，避免不必要的重计算
 */
export const useSnapPoints = ({
  snapPoints = [],
  initialSnap = 0,
  onSnap,
  onClose,
  position = 'bottom',
  open,
  enableGestureRecognition = true,
  fastSwipeThreshold = 0.5,
}: UseSnapPointsProps) => {
  const [currentSnapIndex, setCurrentSnapIndex] = useState(initialSnap);
  const [isDragging, setIsDragging] = useState(false);
  const [dragOffset, setDragOffset] = useState(0);
  const [isInitialized, setIsInitialized] = useState(() => {
    // 立即初始化，如果有snapPoints就设为true
    return open && snapPoints.length > 0;
  }); // 添加初始化状态
  const [hasAutoInitialized, setHasAutoInitialized] = useState(false); // 防止重复自动初始化
  const containerRef = useRef<HTMLDivElement>(null);
  const startPositionRef = useRef(0);
  const startOffsetRef = useRef(0);

  // 手势识别
  const { startGesture, updateGesture, endGesture } = useGestureRecognition({
    velocityThreshold: fastSwipeThreshold,
    velocityHistorySize: 5,
    inertiaDecay: 0.95,
  });

  // 计算 snap point 的实际像素值
  // 说明：
  // - 0 代表关闭；1 代表全屏；(0,1) 按窗口百分比；负数表示距顶部像素；正数为固定像素
  const calculateSnapValue = useCallback(
    (snapPoint: SnapPoint): number => {
      if (!containerRef.current) return 0;

      // 确保引用存在即可，后续使用窗口尺寸进行计算

      // 根据位置确定容器尺寸
      const containerSize =
        position === 'left' || position === 'right'
          ? window.innerWidth
          : window.innerHeight;

      if (snapPoint === 0) return 0; // 关闭状态
      if (snapPoint === 1) return containerSize; // 全屏状态
      if (snapPoint > 0 && snapPoint < 1) return containerSize * snapPoint; // 百分比
      if (snapPoint < 0) return containerSize + snapPoint; // 负值：距离顶部
      return snapPoint; // 正值：具体像素
    },
    [position]
  );

  // 获取当前 snap point 的样式
  // 设计：
  // - bottom/top 使用 height 驱动，left/right 使用 width 驱动
  // - 拖拽中禁用过渡，释放后开启过渡，保证"跟手 + 平滑"
  const getSnapStyles = useCallback(() => {
    if (snapPoints.length === 0) return {}; // 没有吸附点时不应用样式

    // 如果还没有初始化但正在拖拽，使用默认的初始吸附点
    const effectiveSnapIndex = isInitialized ? currentSnapIndex : initialSnap;
    const currentSnap = snapPoints[effectiveSnapIndex] || snapPoints[0] || 0;
    const snapValue = calculateSnapValue(currentSnap);
    const offset = isDragging ? dragOffset : 0;

    const finalValue = snapValue + offset;

    // 调试信息
    if (process.env.NODE_ENV === 'development' && isDragging) {
      console.log('🎨 样式计算:', {
        snapValue,
        offset,
        finalValue,
        isDragging,
        position,
      });
    }

    switch (position) {
      case 'bottom':
        return {
          height: `${Math.max(0, finalValue)}px`,
          // 当拖拽到负值时，使用 transform 向下移动来模拟关闭效果
          transform:
            finalValue < 0
              ? `translateY(${Math.abs(finalValue)}px)`
              : 'translateY(0)',
          transition: isDragging
            ? 'none'
            : 'height 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
        };
      case 'top':
        return {
          height: `${Math.max(0, finalValue)}px`,
          // 当拖拽到负值时，使用 transform 向上移动来模拟关闭效果
          transform:
            finalValue < 0
              ? `translateY(${-Math.abs(finalValue)}px)`
              : 'translateY(0)',
          transition: isDragging
            ? 'none'
            : 'height 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
        };
      case 'left':
        return {
          width: `${Math.max(0, finalValue)}px`,
          height: '100vh', // 左边弹出占满整个屏幕高度
          // 当拖拽到负值时，使用 transform 向左移动来模拟关闭效果
          transform:
            finalValue < 0
              ? `translateX(${-Math.abs(finalValue)}px)`
              : 'translateX(0)',
          transition: isDragging
            ? 'none'
            : 'width 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
        };
      case 'right':
        return {
          width: `${Math.max(0, finalValue)}px`,
          height: '100vh', // 右边弹出占满整个屏幕高度
          // 当拖拽到负值时，使用 transform 向右移动来模拟关闭效果
          transform:
            finalValue < 0
              ? `translateX(${Math.abs(finalValue)}px)`
              : 'translateX(0)',
          transition: isDragging
            ? 'none'
            : 'width 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
        };
      default:
        return {};
    }
  }, [
    snapPoints,
    currentSnapIndex,
    calculateSnapValue,
    isDragging,
    dragOffset,
    position,
    isInitialized,
    initialSnap,
  ]);

  // 找到最近的 snap point
  // 思路：计算当前值与所有吸附点像素值的差，取最小者
  const findNearestSnapIndex = useCallback(
    (currentValue: number): number => {
      if (snapPoints.length === 0) return 0;

      let nearestIndex = 0;
      let nearestDistance = Infinity;

      snapPoints.forEach((snapPoint, index) => {
        const snapValue = calculateSnapValue(snapPoint);
        const distance = Math.abs(currentValue - snapValue);

        if (distance < nearestDistance) {
          nearestDistance = distance;
          nearestIndex = index;
        }
      });

      return nearestIndex;
    },
    [snapPoints, calculateSnapValue]
  );

  // 智能吸附点选择：支持快速滑动时跳过中间点
  const findSmartSnapIndex = useCallback(
    (
      currentValue: number,
      _velocity: number, // 未来可能用到，暂时加下划线避免警告
      direction: number,
      isFastSwipe: boolean,
      predictedEndPosition: number
    ): number => {
      if (!enableGestureRecognition || !isFastSwipe) {
        // 普通模式：选择最近的吸附点
        return findNearestSnapIndex(currentValue);
      }

      // 快速滑动模式：考虑速度和方向
      const currentSnap = snapPoints[currentSnapIndex] || 0;
      const currentSnapValue = calculateSnapValue(currentSnap);
      const targetValue = currentSnapValue + predictedEndPosition;

      // 根据方向和速度选择目标吸附点
      let targetIndex = currentSnapIndex;

      if (direction > 0) {
        // 向下/右滑动：寻找更大的吸附点
        for (let i = currentSnapIndex + 1; i < snapPoints.length; i++) {
          const snapValue = calculateSnapValue(snapPoints[i]);
          if (snapValue >= targetValue) {
            targetIndex = i;
            break;
          }
          // 如果是最后一个点，就选择它
          if (i === snapPoints.length - 1) {
            targetIndex = i;
          }
        }
      } else if (direction < 0) {
        // 向上/左滑动：寻找更小的吸附点
        for (let i = currentSnapIndex - 1; i >= 0; i--) {
          const snapValue = calculateSnapValue(snapPoints[i]);
          if (snapValue <= targetValue) {
            targetIndex = i;
            break;
          }
          // 如果是第一个点，就选择它
          if (i === 0) {
            targetIndex = i;
          }
        }
      }

      // 确保索引在有效范围内
      return Math.max(0, Math.min(targetIndex, snapPoints.length - 1));
    },
    [
      snapPoints,
      calculateSnapValue,
      currentSnapIndex,
      enableGestureRecognition,
      findNearestSnapIndex,
    ]
  );

  // 跳转到指定 snap point（外部按钮或释放吸附都会用到）
  const snapTo = useCallback(
    (index: number) => {
      if (index < 0 || index >= snapPoints.length) return;

      // 使用 flushSync 确保状态立即同步，避免延迟
      flushSync(() => {
        setCurrentSnapIndex(index);
        setDragOffset(0);
        setIsInitialized(true); // 确保初始化状态
        setHasAutoInitialized(true); // 防止自动初始化覆盖用户操作
      });

      const snapValue = snapPoints[index];
      if (snapValue !== undefined) {
        onSnap?.(index, snapValue);

        // 如果吸附到关闭状态（snapValue === 0），触发关闭
        if (snapValue === 0) {
          // 延迟一点时间让动画完成，然后关闭
          setTimeout(() => {
            onClose?.();
          }, 200);
        }
      }
    },
    [snapPoints, onSnap, onClose]
  );

  // 处理拖拽开始：记录起点坐标，设置"跟手"状态
  const handleDragStart = useCallback(
    (event: MouseEvent | TouchEvent) => {
      if (snapPoints.length === 0) return;

      const clientY =
        'touches' in event ? event.touches[0]?.clientY || 0 : event.clientY;
      const clientX =
        'touches' in event ? event.touches[0]?.clientX || 0 : event.clientX;

      startPositionRef.current =
        position === 'left' || position === 'right' ? clientX : clientY;

      // 关键修复：记录当前的dragOffset作为起始偏移，而不是重置为0
      startOffsetRef.current = dragOffset;

      // 调试信息
      if (process.env.NODE_ENV === 'development') {
        console.log('🚀 拖拽开始:', {
          startPosition: startPositionRef.current,
          startOffset: startOffsetRef.current,
          currentDragOffset: dragOffset,
          position,
        });
      }

      // 使用 flushSync 确保状态立即更新，消除拖拽延迟
      flushSync(() => {
        setIsDragging(true);
        setIsInitialized(true); // 确保初始化状态
        // 不重置dragOffset，保持当前位置
      });

      // 启动手势识别
      if (enableGestureRecognition) {
        startGesture(clientX, clientY);
      }
    },
    [
      snapPoints.length,
      position,
      enableGestureRecognition,
      startGesture,
      dragOffset,
    ]
  );

  // 处理拖拽中：计算位移 delta，按方向修正符号
  const handleDrag = useCallback(
    (event: MouseEvent | TouchEvent) => {
      if (!isDragging || snapPoints.length === 0) return;

      // 立即执行，确保拖拽响应无延迟
      const clientY =
        'touches' in event ? event.touches[0]?.clientY || 0 : event.clientY;
      const clientX =
        'touches' in event ? event.touches[0]?.clientX || 0 : event.clientX;

      const currentPosition =
        position === 'left' || position === 'right' ? clientX : clientY;
      let delta = currentPosition - startPositionRef.current;

      // 根据位置调整拖拽方向
      if (position === 'bottom' || position === 'right') {
        delta = -delta;
      }

      const newDragOffset = startOffsetRef.current + delta;
      setDragOffset(newDragOffset);

      // 调试信息（开发环境）
      if (process.env.NODE_ENV === 'development') {
        console.log('🎯 Snap拖拽调试:', {
          isDragging,
          startOffset: startOffsetRef.current,
          delta,
          newDragOffset,
          currentPosition:
            position === 'left' || position === 'right' ? clientX : clientY,
          startPosition: startPositionRef.current,
          snapPointsLength: snapPoints.length,
        });
      }

      // 更新手势识别
      if (enableGestureRecognition) {
        updateGesture(clientX, clientY);
      }
    },
    [
      isDragging,
      snapPoints.length,
      position,
      enableGestureRecognition,
      updateGesture,
    ]
  );

  // 处理拖拽结束：计算当前值，智能吸附到目标点
  const handleDragEnd = useCallback(() => {
    if (!isDragging || snapPoints.length === 0) return;

    // 立即停止拖拽状态
    flushSync(() => {
      setIsDragging(false);
    });

    // 计算当前值
    const currentSnap = snapPoints[currentSnapIndex] || 0;
    const currentValue = calculateSnapValue(currentSnap) + dragOffset;

    let targetIndex: number;

    if (enableGestureRecognition) {
      // 获取手势识别结果
      const gestureResult = endGesture();

      // 使用智能吸附点选择
      targetIndex = findSmartSnapIndex(
        currentValue,
        gestureResult.velocity,
        gestureResult.direction,
        gestureResult.isFastSwipe,
        gestureResult.predictedEndPosition
      );
    } else {
      // 普通模式：选择最近的吸附点
      targetIndex = findNearestSnapIndex(currentValue);
    }

    // 吸附到目标点
    snapTo(targetIndex);
  }, [
    isDragging,
    snapPoints,
    currentSnapIndex,
    calculateSnapValue,
    dragOffset,
    enableGestureRecognition,
    endGesture,
    findSmartSnapIndex,
    findNearestSnapIndex,
    snapTo,
  ]);

  // 初始化：立即设置初始状态，确保拖拽无延迟
  useEffect(() => {
    if (open && snapPoints.length > 0 && !hasAutoInitialized) {
      // 立即设置所有必要状态，确保拖拽无延迟
      const validInitialSnap = Math.max(
        0,
        Math.min(initialSnap, snapPoints.length - 1)
      );

      // 使用普通的 setState，避免在 useEffect 中使用 flushSync
      setIsInitialized(true);
      setCurrentSnapIndex(validInitialSnap);
      setHasAutoInitialized(true);
      setDragOffset(0); // 确保偏移量为 0

      // 通知外部状态变化
      const snapValue = snapPoints[validInitialSnap];
      if (snapValue !== undefined) {
        onSnap?.(validInitialSnap, snapValue);
      }
    } else if (!open) {
      // 关闭时重置初始化状态
      setIsInitialized(false);
      setHasAutoInitialized(false);
      setCurrentSnapIndex(initialSnap);
      setDragOffset(0);
    }
  }, [open, snapPoints, initialSnap, onSnap, hasAutoInitialized]);

  // 优化：预绑定拖拽事件，避免第一次拖拽延迟
  const isEventsBound = useRef(false);

  useEffect(() => {
    if (snapPoints.length > 0 && !isEventsBound.current) {
      const handleMouseMove = (e: MouseEvent) => {
        if (isDragging) handleDrag(e);
      };
      const handleMouseUp = () => {
        if (isDragging) handleDragEnd();
      };
      const handleTouchMove = (e: TouchEvent) => {
        if (isDragging) handleDrag(e);
      };
      const handleTouchEnd = () => {
        if (isDragging) handleDragEnd();
      };

      // 预绑定所有事件监听器，使用 passive: false 确保可以 preventDefault
      document.addEventListener('mousemove', handleMouseMove, {
        passive: false,
      });
      document.addEventListener('mouseup', handleMouseUp, {
        passive: false,
      });
      document.addEventListener('touchmove', handleTouchMove, {
        passive: false,
      });
      document.addEventListener('touchend', handleTouchEnd, {
        passive: false,
      });

      isEventsBound.current = true;

      return () => {
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
        document.removeEventListener('touchmove', handleTouchMove);
        document.removeEventListener('touchend', handleTouchEnd);
        isEventsBound.current = false;
      };
    }
  }, [snapPoints.length, handleDrag, handleDragEnd, isDragging]);

  return {
    containerRef,
    currentSnapIndex,
    snapStyles: getSnapStyles(),
    snapTo,
    handleDragStart,
    isDragging,
    hasSnapPoints: snapPoints.length > 0,
    isInitialized,
  };
};
